import Vue from 'vue'
import VueRouter from 'vue-router'
// 导入vuex模块
import store from '../store/index'

// 导入登录的组件界面
// import Login from '../views/login/login.vue'
// 路由懒加载
const Login = () => import('../views/login/login.vue')
// 导入main主页组件
// import Main from '../views/main/main.vue'
const Main = () => import('../views/main/main.vue')
// 导入home和user两个子路由组件
// import Home from '../views/main/Home.vue'
// import User from '../views/main/User.vue'
const Home = () => import('../views/main/Home.vue')
const User = () => import('../views/main/User.vue')

// 导入搜索组件：
// import Search from '@/views/Search/Search.vue'
const Search = () => import('@/views/Search/Search.vue')

// 导入搜索结果页
// import SearchResult from '@/views/Search/SearchResult.vue'
const SearchResult = () => import('@/views/Search/SearchResult.vue')

// 导入文章详情组件
// import ArticleDetail from '@/views/ArticleDetail/ArticleDetail.vue'
const ArticleDetail = () => import('@/views/ArticleDetail/ArticleDetail.vue')

// 在路由模块中导入用户资料组件：
// import UserEdit from '@/views/UserEdit/UserEdit.vue'
const UserEdit = () => import('@/views/UserEdit/UserEdit.vue')

// 导入小思同学的组件页面
// import Chat from '@/views/Chat/Chat.vue'
const Chat = () => import('@/views/Chat/Chat.vue')

// 解决 vue-router 内部的报错的问题：
// 1. 将 VueRouter 本身提供的 $router.push 方法转存到常量中
const originalPush = VueRouter.prototype.push
// 2. 自定义 $router.push 方法，在内部调用原生的 originalPush 方法进行路由跳转；并通过 .catch 捕获错误
VueRouter.prototype.push = function push (location, onResolve, onReject) {
  if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
  // 通过 .catch 捕获错误
  return originalPush.call(this, location).catch(err => err)
}

Vue.use(VueRouter)
// 路由规则数组
const routes = [
  // 带有name属性的路由规则叫做命名路由
  { path: '/login', component: Login, name: 'login' },
  {
    path: '/',
    component: Main,
    // 如果通过children属性加载了默认子路由，name父路由规则不需要加name属性
    // name: 'main',
    children: [
      // path为空字符串的子路由规则，是默认子路由 为 Home 组件的路由规则添加 meta 元信息(名字是任意取的，isRecord是否记录，记录到top)
      { path: '', component: Home, name: 'home', meta: { isRecord: true, top: 0 } },
      // 注意：子路由规则不建议以/开头
      { path: 'user', component: User, name: 'user' }
    ]
  },
  // 搜索组件的路由规则
  { path: '/search', component: Search, name: 'search' },
  // 搜索结果页的路由规则 :kw 是动态参数，:定义动态参数 component指定组件（与上面的import相同）
  // porps: true表示为当前路由开启props传参，开启成功之后就可以在component指向的组件中通过props接收路由参数
  { path: '/search/:kw', component: SearchResult, name: 'search-result', props: true, meta: { isRecord: true, top: 0 } },
  // 文章详情的路由规则 :id
  { path: '/article/:id', component: ArticleDetail, name: 'art-detail', props: true, meta: { isRecord: true, top: 0 } },
  // 编辑用户资料的路由规则
  { path: '/user/edit', component: UserEdit, name: 'user-edit' },
  // 小思聊天的路由规则
  { path: '/chat', component: Chat, name: 'chat' }
]

// 创建路由实例对象
const router = new VueRouter({
  routes
})

// 挂载全局前置导航守卫
// 注意：如果某个组件式要难过路由加载出来的，name就可以像声明生命周期一样声明组件内的导航组件，这个组件内使用
router.beforeEach((to, from, next) => {
  // 判断用户访问的path地址是否为/user或/user/edit
  // 如果是，应该改判断用户是否登录
  // 如何判断用户是否登录：可以从vuex总读取一下token的值，如果有之证明登陆了，放行即可
  // 如果没有token的值，证明没有登陆，强制用户跳转登录页
  if (to.path === '/user' || to.path === '/user/edit') {
    // 访问的是有权限的页面，需要判断用户是否登录了
    const tokenStr = store.state.tokenInfo.token
    if (tokenStr) {
      // 有token 放行
      next()
    } else {
      // 访问的是有权限的页面，但是没有登录，强制跳转到登录页面
      // to是访问的地址，因为没有权限所以没有进入，但是to总还包含着地址
      next('/login?pre=' + to.fullPath)
    }
  } else {
    // 访问的是不需要权限的页面，直接放行即可
    next()
  }
})

// 全局后置导航守卫
router.afterEach((to, from, next) => {
  // 形参中的to是目标路由，形参中的from是要离开的路由
  // 因此要读取home路由中的元信息应该从to上获取
  if (to.meta.isRecord === true) {
    // 证明to这个路由中保存了元信息
    // 把元信息读取出来赋值给浏览器滚动条

    // setTimeout(() => {
    //   window.scrollTo(0, to.meta.top)
    // }, 0)
    // 换个方式
    Vue.nextTick(function () {
      window.scrollTo(0, to.meta.top)
    })
  }
})

export default router
